#include <linux/init.h>
#include <linux/bug.h>
#include <linux/of/fdt.h>
#include <libfdt.h>

/*
 * alloc_reserved_mem_array() - allocate memory for the reserved_mem
 * array using memblock
 *
 * This function is used to allocate memory for the reserved_mem
 * array according to the total number of reserved memory regions
 * defined in the DT.
 * After the new array is allocated, the information stored in
 * the initial static array is copied over to this new array and
 * the new array is used from this point on.
 */
static void __init alloc_reserved_mem_array(void)
{
}

/*
 * __reserved_mem_check_root() - check if #size-cells, #address-cells provided
 * in /reserved-memory matches the values supported by the current implementation,
 * also check if ranges property has been provided
 */
static int __init __reserved_mem_check_root(unsigned long node)
{
    return 0;
}

static void __init __rmem_check_for_overlap(void)
{
}

/*
 * fdt_reserved_mem_save_node() - save fdt node for second pass initialization
 */
static void __init fdt_reserved_mem_save_node(unsigned long node, const char *uname,
                                              phys_addr_t base, phys_addr_t size)
{
}

/**
 * fdt_scan_reserved_mem_reg_nodes() - Store info for the "reg" defined
 * reserved memory regions.
 *
 * This function is used to scan through the DT and store the
 * information for the reserved memory regions that are defined using
 * the "reg" property. The region node number, name, base address, and
 * size are all stored in the reserved_mem array by calling the
 * fdt_reserved_mem_save_node() function.
 */
void __init fdt_scan_reserved_mem_reg_nodes(void)
{
    int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32);
    const void *fdt = initial_boot_params;
    phys_addr_t base, size;
    const __be32 *prop;
    int node, child;
    int len;

    if (!fdt)
        return;

    node = fdt_path_offset(fdt, "/reserved-memory");
    if (node < 0)
    {
        pr_info("Reserved memory: No reserved-memory node in the DT\n");
        return;
    }

    /* Attempt dynamic allocation of a new reserved_mem array */
    alloc_reserved_mem_array();

    if (__reserved_mem_check_root(node))
    {
        pr_err("Reserved memory: unsupported node format, ignoring\n");
        return;
    }

    fdt_for_each_subnode(child, fdt, node)
    {
        const char *uname;

        prop = of_get_flat_dt_prop(child, "reg", &len);
        if (!prop)
            continue;
        if (!of_fdt_device_is_available(fdt, child))
            continue;

        uname = fdt_get_name(fdt, child, NULL);
        if (len && len % t_len != 0)
        {
            pr_err("Reserved memory: invalid reg property in '%s', skipping node.\n",
                   uname);
            continue;
        }

        if (len > t_len)
            pr_warn("%s() ignores %d regions in node '%s'\n",
                    __func__, len / t_len - 1, uname);

        base = dt_mem_next_cell(dt_root_addr_cells, &prop);
        size = dt_mem_next_cell(dt_root_size_cells, &prop);

        if (size)
            fdt_reserved_mem_save_node(child, uname, base, size);
    }

    /* check for overlapping reserved regions */
    __rmem_check_for_overlap();
}
